package GUI;
import processing.core.PFont;

/**
 * Tag Cloud by Wray Bowling
 */
// A lot of the code in this class is by Wray Bowling, I changed just the things I needed to behave differently.
public class TagCloud {

	public int xRect;
	public int yRect;
	public int width;
	public int height;
	CommonWordsButton cwb;
	AffineCharactersButton acb;



	String fontFile = "ComicSans-48.vlw";
	float baseline_ratio = (float)0.28;
	int large_font = 74;
	int small_font = 20;
	PFont font;
	int most;
	int least;

	float spring = (float)0.02;
	int numWords;
	Tag[] Cloud; 


	public TagCloud(CommonWordsButton cwb){
		xRect=387;
		yRect=500;
		width = 640;
		height = 320;
		this.cwb = cwb;
		Cloud = new Tag[cwb.c.getCommonWords().size()];
		most = cwb.c.getCommonWords().get(0).getCount();
		least = cwb.c.getCommonWords().get(cwb.c.getCommonWords().size()-1).getCount();
		numWords = cwb.c.getCommonWords().size();
		font = Utils.globalProcessing.createFont("SansSerif",20);
		Utils.globalProcessing.textFont(font);
		for (int i = 0; i < numWords; i++) {
			//Cloud[i] = new Tag(Cloud, i, tags[i], tagtally[i], xRect, yRect);
			Cloud[i] = new Tag(Cloud, i, cwb.c.getCommonWords().get(i).getWord(), cwb.c.getCommonWords().get(i).getCount(), xRect, yRect);
		}
	}

	public TagCloud(AffineCharactersButton acb){
		xRect=387;
		yRect=500;
		width = 640;
		height = 320;
		this.acb = acb;
		Cloud = new Tag[acb.c.getAffineCharacters().size()];
		most = acb.c.getAffineCharacters().get(0).getAffinity();
		least = acb.c.getAffineCharacters().get(acb.c.getAffineCharacters().size()-1).getAffinity();
		numWords = acb.c.getAffineCharacters().size();
		font = Utils.globalProcessing.createFont("SansSerif",20);
		Utils.globalProcessing.textFont(font);
		for (int i = 0; i < numWords; i++) {
			//Cloud[i] = new Tag(Cloud, i, tags[i], tagtally[i], xRect, yRect);
			Cloud[i] = new Tag(Cloud, i, acb.c.getAffineCharacters().get(i).getCharacter().getShortName(), acb.c.getAffineCharacters().get(i).getAffinity(), xRect, yRect);
		}
		cwb=null;
	}


	void draw() 
	{
		Utils.globalProcessing.rectMode(Utils.globalProcessing.CENTER);
		Utils.globalProcessing.fill(Utils.backGroundColor); //200
		//Utils.globalProcessing.stroke(80);
		//Utils.globalProcessing.strokeWeight(1);
		Utils.globalProcessing.noStroke();
		Utils.globalProcessing.rect(Utils.graphAreaCenterX, Utils.graphAreaCenterY+25,Utils.graphAreaWidth, Utils.graphAreaHeight+50);

		//Utils.globalProcessing.background(0);
		Utils.globalProcessing.stroke(255,20);
		//Utils.globalProcessing.line(xRect-width/2,yRect-height/2,xRect+width/2,yRect+height/2);
		//Utils.globalProcessing.line(xRect+width/2,yRect-height/2,xRect-width/2,yRect+height/2);
		//Utils.globalProcessing.line(xRect-width/2, yRect - 24,xRect+width/2, yRect - 24);
		//Utils.globalProcessing.line(xRect-width/2, yRect + 24,xRect+width/2, yRect + 24);
		for (int i = 0; i < numWords; i++) {
			Cloud[i].collide();
			Cloud[i].move();
			Cloud[i].display();  
		}
		Utils.globalProcessing.rectMode(Utils.globalProcessing.CORNER);


	}

	class Tag {
		float x, y;
		float word_width;
		int font_size;

		float vx = 0;
		float vy = 0;
		int id;
		Tag[] others;

		Tag(Tag[] others, int id, String word, int occurance, int x, int y) {
			this.x = x + Utils.globalProcessing.random(-100, 100);
			this.y = y + Utils.globalProcessing.random(-100, 100);
			font_size = (int)(Utils.globalProcessing.map(occurance, least, most, small_font, large_font));
			Utils.globalProcessing.textFont(font, font_size);
			this.word_width = Utils.globalProcessing.textWidth(word);

			this.id = id;
			this.others = others;
		} 

		/* I mucked with this function pretty heavily, but to no avail :( */

		void collide() {
			for (int i = id + 1; i < numWords; i++) {
				float dx = others[i].x + others[i].word_width/2 - x + word_width/2;
				float dy = others[i].y + others[i].font_size/2 - y + font_size/2;

				float minDistX = word_width + others[i].word_width;
				float minDistY = font_size + others[i].font_size;

				if ( (dx < minDistX) && (dy < minDistY) ){ 
					float angle = Utils.globalProcessing.atan2(dy, dx);
					float targetX = x + Utils.globalProcessing.cos(angle) * minDistX;
					float ax = (targetX - others[i].x) * spring;
					vx -= ax;
					others[i].vx += ax;

					float targetY = y + minDistY;
					float ay = (targetY - others[i].y) * spring;
					vy -= ay;
					others[i].vy += ay;
				}

			}   
		}

		void move() {
			vx *= 0.1;
			vy *= 0.75;
			x += vx;
			y += vy;
			if (x + word_width/2 > xRect+width/2) {
				x = xRect+width/2 - word_width/2;
				vx *= -0.5; 
			}
			else if (x - word_width/2 < 0) {
				x = word_width/2;
				vx *= -0.5;
			}
			if (y + font_size/2 > yRect+height/2) {
				y = yRect +height/2 - font_size/2;
				vy *= -0.5; 
			} 
			else if (y - font_size/2 < 0) {
				y = font_size/2;
				vy *= -0.5;
			}
		}

		void display() {
			Utils.globalProcessing.fill(255,30);
			Utils.globalProcessing.rectMode(Utils.globalProcessing.CENTER);
			Utils.globalProcessing.rect(x,y+20,word_width,font_size); 
			Utils.globalProcessing.fill(255);
			Utils.globalProcessing.textFont(font, font_size);
			if(cwb!=null)
				Utils.globalProcessing.text(cwb.c.getCommonWords().get(id).getWord(), (int)(x - word_width/2), (int)(y+20 + font_size * baseline_ratio));
			else
				Utils.globalProcessing.text(acb.c.getAffineCharacters().get(id).getCharacter().getShortName(), (int)(x - word_width/2), (int)(y+20 + font_size * baseline_ratio));
			

		}
	} 
}